package br.edu.unicentro.mymib.security;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import br.edu.unicentro.mymib.base.EntityManagerService;
import br.edu.unicentro.mymib.entity.Administrador;
import br.edu.unicentro.mymib.entity.Usuario;

public class LoginService implements LoginModule {

	private Subject subject;
	private CallbackHandler callbackHandler;
	private Map sharedState;

	private boolean commitSucceeded = false;
	private boolean succeeded = false;

	private String username;
	private String password;
	private User user;
	private Set<Role> group;

	public void initialize(Subject subject, CallbackHandler callbackHandler,
			Map sharedState, Map options) {
		this.subject = subject;
		this.callbackHandler = callbackHandler;
		this.sharedState = sharedState;
		group = new HashSet<Role>();
	}

	public boolean login() throws LoginException {

		try {
			NameCallback nameCallback = new NameCallback("Username");
			PasswordCallback passwordCallback = new PasswordCallback(
					"Password", false);

			Callback[] callbacks = new Callback[] { nameCallback,
					passwordCallback };
			callbackHandler.handle(callbacks);

			username = nameCallback.getName();
			password = new String(passwordCallback.getPassword());

			passwordCallback.clearPassword();

			succeeded = false;

			String role = "";

			if (username.equals("admin")) {
				Administrador adm = Administrador.buscar();
				if (adm.validarSenha(password)) {
					succeeded = true;
					role = "ADMIN";

				}
			} else {

				Usuario usuario = Usuario.buscarPorEmail(username);

				if ((usuario != null) && (!usuario.isBloqueado())) {
					succeeded = usuario.validarSenha(password);
					if (succeeded) {
						role = "GRANTED";
					}

				}
			}

			if (succeeded) {
				user = new User(username);
				group.add(new Role(role));
				sharedState.put("javax.security.auth.principal", user);
				sharedState.put("javax.security.auth.roles", group);
			}

			return succeeded;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean commit() {
		try {
			subject.getPrincipals().add(user);
			for (Role role : group) {
				subject.getPrincipals().add(role);
			}
			commitSucceeded = true;
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public boolean abort() {
		try {
			succeeded = false;
			if (commitSucceeded) {
				logout();
			}
			this.subject = null;
			this.callbackHandler = null;
			this.sharedState = null;
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public boolean logout() {
		try {
			succeeded = false;
			commitSucceeded = false;
			subject.getPrincipals().remove(group);
			subject.getPrincipals().remove(user);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

}
